package com.unisyou.controller;

import com.unisyou.config.PropertiesConfig;
import com.unisyou.utils.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

@Controller
@RequestMapping("/wx")
@Slf4j
@AllArgsConstructor
public class WxController {
    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private PropertiesConfig propertiesConfig;
    private final WxMpMessageRouter messageRouter;

    @GetMapping(produces = "text/plain;charset=utf-8")
    public void authGet(@RequestParam(name = "signature", required = false) String signature,
                        @RequestParam(name = "timestamp", required = false) String timestamp,
                        @RequestParam(name = "nonce", required = false) String nonce,
                        @RequestParam(name = "echostr", required = false) String echostr,
                        HttpServletResponse response) throws IOException {
        log.info("\n接收到来自微信服务器的认证消息：[{}, {}, {}, {}]", signature, timestamp, nonce, echostr);
        PrintWriter out = response.getWriter();
        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }
        if (wxMpService.checkSignature(timestamp, nonce, signature)) {
            out.println(echostr);
        }
    }

    @PostMapping(produces = "application/xml; charset=UTF-8")
    public void post(@RequestBody String requestBody, @RequestParam("signature") String signature,
                     @RequestParam(name = "encrypt_type", required = false) String encType,
                     @RequestParam(name = "msg_signature", required = false) String msgSignature,
                     @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce,
                     HttpServletResponse response,HttpServletRequest request) throws IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        log.info("接收微信请求：[signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[{}] ",
                signature, encType, msgSignature, timestamp, nonce, requestBody);
        PrintWriter out = response.getWriter();
        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }
        String outString = null;
        if (encType == null) {
            // 明文传输的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
            WxMpXmlOutMessage outMessage = this.route(inMessage);
            if(outMessage != null){
                outString = outMessage.toXml();
            }
        } else if ("aes".equals(encType)) {
            // aes加密的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody,
                    wxMpService.getWxMpConfigStorage(), timestamp, nonce, msgSignature);
            log.debug("消息解密后内容为：{} ", inMessage.toString());
            WxMpXmlOutMessage outMessage = this.route(inMessage);
            if (outMessage != null) {
                outString = outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());
            }
        }
        out.println(outString);
        log.info("组装回复信息：{}", outString);
    }

    @ResponseBody
    @GetMapping("/getRedirectUrl")
    public String getRedirectUrl() {
        String redirect_uri = "";
        try {
            redirect_uri = java.net.URLEncoder.encode(propertiesConfig.getRedirectUri(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String oauth2Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxMpService.getWxMpConfigStorage().getAppId() + "&redirect_uri=" + redirect_uri
                + "&response_type=code&scope=" + WxConsts.OAuth2Scope.SNSAPI_USERINFO + "&state=STATE#wechat_redirect";
        return oauth2Url;
    }

    @RequestMapping("/getOpenid")
    @ResponseBody
    public R getOpenid(@RequestParam(name = "code", required = false) String code) {
        WxMpUser wxMpUser = null;
        if (code != null || !(code.equals(""))) {
            try {
                WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
                wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
            } catch (WxErrorException e) {
                e.printStackTrace();
            }
        } else {
            return R.error();
        }
        return R.ok().put("openid", wxMpUser.getOpenId());
    }

    /**
     * 微信操作路由
     * @param message
     * @return
     */
    private WxMpXmlOutMessage route(WxMpXmlMessage message) {
        try {
            return this.messageRouter.route(message);
        } catch (Exception e) {
            log.error("路由消息时出现异常！", e);
        }
        return null;
    }
}
